﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using QLTT.Models;
using QLTT.Commands;
using System.Windows.Input;
using System.Text.RegularExpressions;
using QLTT.Properties;
using System.Windows;

namespace QLTT.ViewModels
{
    class StudentViewModel:WorkspaceViewModel,System.ComponentModel.IDataErrorInfo
    {
        private Student _student;
        private icanDataContext _dataContext;
        private DelegateCommand _saveCommand;
        private DelegateCommand _editCommand;
        private DelegateCommand _cancelCommand;
        private DelegateCommand _saveAndRegisterClassCommand;
        private DelegateCommand _possibleScheduleCommand;
        Regex rxValidate;                
        private bool _isSelected;
        private bool _isEdit = true;
        private List<PossibleScheduleViewModel> _lstSchedule;        
        public StudentViewModel(icanDataContext dataContext)
        {
            _dataContext = dataContext;
            _student = new Student();
            this.DateOfBirth = new DateTime(1990, 5, 15);
            base.DisplayName = Properties.Resources.Base_DisplayName_Student_New;
        }
        public StudentViewModel(icanDataContext dataContext, Student student)
        {
            _student = student;
            _dataContext = dataContext;
            base.DisplayName = Properties.Resources.Base_DisplayName_Student_Edit;
        }
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new DelegateCommand(Save);
                }
                return _saveCommand;
            }
        }
        public ICommand SaveAndRegisterClassCommand
        {
            get
            {
                if (_saveAndRegisterClassCommand == null)
                    _saveAndRegisterClassCommand = new DelegateCommand(SaveAndRegisterClass);
                return _saveAndRegisterClassCommand;
            }
        }
        public ICommand EditCommand
        {
            get
            {
                if (_editCommand == null)
                {
                    _editCommand = new DelegateCommand(Edit);
                }
                return _editCommand;
            }
        }
        public ICommand CancelCommand
        {
            get
            {
                if (_cancelCommand == null)
                {
                    _cancelCommand = new DelegateCommand(Cancel);
                }
                return _cancelCommand;
            }
        }
        public ICommand PossibleScheduleCommand
        {
            get
            {
                if (_possibleScheduleCommand == null)
                {
                    _possibleScheduleCommand = new DelegateCommand(SelectPossibleSchedule);
                }
                return _possibleScheduleCommand;
            }
        }
        //Insert when add student for the first time
        private void Save()
        {
            try
            {
                if(SaveOrUpdate())
                    Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceRemove, this);
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("Application", ex.ToString(), System.Diagnostics.EventLogEntryType.Error);
                this.ErrorMsg = Resources.ErrorMessage_General;
            }
        }
        private void SaveAndRegisterClass()
        {
            try
            {
                if (SaveOrUpdate())
                {
                    StudentClassFeeViewModel studentClassFeeVM = new StudentClassFeeViewModel(_dataContext, _student);
                    Mediator.NotifyColleagues<StudentClassFeeViewModel>(Messages.WorkspaceAdd, studentClassFeeVM);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("Application", ex.ToString(), System.Diagnostics.EventLogEntryType.Error);
                this.ErrorMsg = Resources.ErrorMessage_General;
            }
        }
        private bool SaveOrUpdate()
        {
            if (_dataContext == null || _student == null)
                    return false;
            string[] properties = { "Name", "Email", "DateOfBirth" };
            if (!ValidateData(properties))
                return false;
            bool isInsert = _student.ID == 0;
            if (isInsert)
            {
                //Không chọn lớp
                _dataContext.Students.InsertOnSubmit(_student);
            }
            _dataContext.SubmitChanges();
            if (isInsert)
            {
                foreach (PossibleScheduleViewModel sVM in this.PosibleSchedules)
                {
                    sVM.Student = this;
                    sVM.Save();
                }
                Mediator.NotifyColleagues<Student>(Messages.ListStudentUpdated, _student);
            }
            return true;
                
        }
        private void Edit()
        {
            if (_dataContext == null || _student == null)
                return;
           
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, this);
        }
        private void Cancel()
        {
            if(_student.ID > 0)
                _dataContext.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, _student);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceRemove, this);
        }
        private void SelectPossibleSchedule()
        {
            AllPossibleScheduleViewModel sVM = new AllPossibleScheduleViewModel(this, _dataContext);
            Mediator.NotifyColleagues<AllPossibleScheduleViewModel>(Messages.WorkspaceAdd, sVM);
        }
                
        public long ID
        {
            get { return _student.ID; }
        }
        public string Name
        {
            get { return _student.Name; }
            set
            {
                if (_student.Name == value) return;
                _student.Name = value;
                base.OnPropertyChanged("Name");
            }
        }
        public string Address
        {
            get { return _student.Address; }
            set
            {
                if (_student.Address == value) return;
                _student.Address = value;
                base.OnPropertyChanged("Address");
            }
        }
        public System.Nullable<DateTime> DateOfBirth
        {
            get { return _student.DateOfBirth; }
            set
            {
                if (_student.DateOfBirth == value) return;
                _student.DateOfBirth = value;
                base.OnPropertyChanged("DateOfBirth");
            }
        }
        public string Job
        {
            get { return _student.Job; }
            set
            {
                if (_student.Job == value) return;
                _student.Job = value;
                base.OnPropertyChanged("Job");
            }
        }
        public string Email
        {
            get { return _student.Email; }
            set
            {
                if (_student.Email == value) return;
                _student.Email = value;
                base.OnPropertyChanged("Email");
            }
        }
        public string ContactInfo
        {
            get { return _student.ContactInfo; }
            set
            {
                if (_student.ContactInfo == value) return;
                _student.ContactInfo = value;
                base.OnPropertyChanged("ContactInfo");
            }
        }
        public System.Nullable<double> EntranceMark
        {
            get { return _student.EntranceMark; }
            set
            {
                if (_student.EntranceMark == value) return;
                _student.EntranceMark = value;
                base.OnPropertyChanged("EntranceMark");
            }
        }
        public DateTime LastUpdated
        {
            get { return _student.LastUpdated.Value; }
            set
            {
                if (_student.LastUpdated.Value == value) return;
                _student.LastUpdated = value;
                base.OnPropertyChanged("LastUpdated");
            }
        }
        #region Some field to get more
        public string ClasseNames
        {
            get
            {
                var query = _dataContext.StudentClasses.Where(scls => scls.Student == _student.ID);
                List<long> lstClassId = query.Select(cStudent => cStudent.Class).ToList();
                List<string> lstClassName = _dataContext.Classes.Where(cls => lstClassId.Contains(cls.ID)).Select(cls => cls.Name).ToList();
                //string sClassName="";
                //foreach (string sName in lstClassName)
                //    sClassName = sClassName + sName +", ";
                //if (sClassName.Length > 0) sClassName.Remove(sClassName.Length - 1);
                return string.Join(", ", lstClassName.ToArray());
                //return sClassName;
            }
        }
        #endregion
        public List<PossibleScheduleViewModel> PosibleSchedules
        {
            get
            {
                if (_lstSchedule != null)
                    return _lstSchedule;
                List<PosibleSchedule> lstSchedule = _student.PosibleSchedules.ToList();
                _lstSchedule = new List<PossibleScheduleViewModel>();
                foreach (PosibleSchedule schedule in lstSchedule)
                    _lstSchedule.Add(new PossibleScheduleViewModel(schedule, _dataContext));

                return _lstSchedule;
            }
        }
        public string ScheduleDisplayText
        {
            get
            {
                List<List<PossibleScheduleViewModel>> lstPossibleScheduleViewModels = new List<List<PossibleScheduleViewModel>>();
                long prevClassTime = -1;
                foreach (PossibleScheduleViewModel sVM in this.PosibleSchedules)
                {
                    if (sVM.ClassTime.ID != prevClassTime)
                    {
                        List<PossibleScheduleViewModel> sVMs = new List<PossibleScheduleViewModel>();
                        sVMs.Add(sVM);
                        lstPossibleScheduleViewModels.Add(sVMs);
                        prevClassTime = sVM.ClassTime.ID;
                    }
                    else
                        lstPossibleScheduleViewModels[lstPossibleScheduleViewModels.Count - 1].Add(sVM);
                }
                //formulate the string
                List<string> classTimeStrings = new List<string>();
                foreach (List<PossibleScheduleViewModel> lstPossibleScheduleViewModel in lstPossibleScheduleViewModels)
                {
                    List<string> dOWs = new List<string>();
                    foreach (PossibleScheduleViewModel sVM in lstPossibleScheduleViewModel)
                    {
                        dOWs.Add(ViewModelBase.DayOfWeeks[sVM.DayOfWeek]);
                    }
                    classTimeStrings.Add(string.Format("{0} {1}", string.Join(",", dOWs.ToArray()), lstPossibleScheduleViewModel[0].FullName));
                }
                return string.Join("; ", classTimeStrings.ToArray());
            }
        }
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value == _isSelected)
                    return;

                _isSelected = value;
                IsEdit = false;
                base.OnPropertyChanged("IsSelected");
            }
        }
        public bool IsEdit
        {
            get { return _isEdit; }
            set
            {
                if (value == _isEdit) return;
                _isEdit = value;
            }

        }
        [MediatorLib.MediatorMessageSink(Messages.ListScheduleUpdated, ParameterType = typeof(List<PossibleScheduleViewModel>))]
        public void UpdateSchedule(List<PossibleScheduleViewModel> lstSVM)
        {
            this.OnPropertyChanged("ScheduleDisplayText");
        }
        #region IDataErrorInfo Members

        public string Error
        {
            get { return null; }
        }

        public string this[string property]
        {
            get
            {
                string msg = null;
                switch (property)
                {
                    case "Name":
                        if (string.IsNullOrEmpty(this.Name))
                            msg = Resources.ValidationStudentName_Error;
                        break;
                    case "Email":
                        if (string.IsNullOrEmpty(this.Email))
                            break;
                        rxValidate = new Regex(@"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$", RegexOptions.Singleline);
                        if (!rxValidate.IsMatch(this.Email))
                            msg = Resources.ValidationTeacherEmail_Error;
                        break;
                    case "DateOfBirth":
                        if (this.DateOfBirth == null || DateTime.Today.Year <= this.DateOfBirth.Value.Year || DateTime.Today.Year-this.DateOfBirth.Value.Year > 99)
                        {
                            msg = Resources.ValidationStudentDateOfBirth_Error;
                        }
                        
                        break;
                    case "EntranceMark":
                        break;
                    case "Address":
                        break;
                    case "Job":
                        break;
                    case "ContactInfo":
                        break;
                    default:
                        throw new ArgumentException(
                            Resources.ValidationDefaultException_Error + property);
                }
                return msg;
            }
        }

        #endregion // IDataErrorInfo Members
    }
}
